﻿using Newtonsoft.Json.Linq;

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

using Utils;

namespace MicroDb.Mysql
{


    abstract class MysqlResolveBase
    {
        /// <summary>
        /// 字段修饰
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public string CostName(string name)
        {
            return $"`{MysqlNameChange(name)}`";
        }


        /// <summary>
        /// mysql 命名 下划线分割
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private string MysqlNameChange(string name)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var ch in name)
            {
                if (ValidatorHelper.Between(ch, 'A', 'Z'))
                {
                    if (sb.Length > 0)
                        sb.Append('_');
                    sb.Append((char)(ch + 0x20));
                }
                else
                {
                    sb.Append(ch);
                }
            }
            return sb.ToString();
        }

        protected string Suffix { get; set; }

        protected bool AutoCreate { get; set; }

        protected readonly SqlExecute sqlExecute;
        public MysqlResolveBase(SqlExecute sqlExecute)
        {
            if (sqlExecute != null)
            {
                this.sqlExecute = sqlExecute;
            }
        }
        public static MysqlResolveBase CreateResolve(Expression expression, MysqlResolveBase parent = null, Dictionary<string, string> baseTabs = null, SqlExecute sqlExecute = null)
        {
            if (expression.NodeType == ExpressionType.Call)
            {
                MethodCallExpression call = expression as MethodCallExpression;
                switch (call.Method.Name)
                {
                    case "Add":
                    case "AddRange":
                    case "AddOrUpdate":
                    case "Update":
                    case "UpdateColumns":
                    case "Delete":
                        return new MysqlResolveNonQuery(call, sqlExecute);
                    default:
                        return new MysqlResolveQuery(call, sqlExecute, baseTabs, parent);
                }
            }
            return new MysqlResolveNone(expression, sqlExecute);
        }

        protected MysqlResolveBase Parent;

        /// <summary>
        /// 缩写
        /// </summary>
        protected string Abridge;

        public void CreateAbridge()
        {
            int i = 1;
            var p = Parent;
            while (p != null)
            {
                p = p.Parent;
                i++;
            }
            Abridge = "TB" + i;
        }

        protected Type TableType { get; set; }

        protected Dictionary<string, string> BaseTabs = new Dictionary<string, string>();

        protected Dictionary<string, object> Args = new Dictionary<string, object>();

        protected Dictionary<string, Type> rept;

        /// <summary>
        /// 最佳参数
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        protected string AppendArg(string name, object value, string format = null)
        {
            if (value is JToken)
            {
                value = value.ToString();
            }
            if (this.Parent != null)
            {
                return this.Parent.AppendArg(name, value, format);
            }
            int index = 0;
            name = "@" + name;
            string temp = name;
            while (Args.ContainsKey(temp))
            {
                temp = name + (++index);
            }
            if (format == null)
            {
                Args.Add(temp, value);
            }
            else
            {
                Args.Add(temp, string.Format(format, value.ToString()));
            }
            return temp;
        }

        public virtual string BuildSql(bool isEasy = false)
        {
            return "";
        }

        /// <summary>
        /// 获取默认标记
        /// </summary>
        /// <param name="lambda"></param>
        /// <returns></returns>
        protected Dictionary<string, string> GetDefaultParameters(LambdaExpression lambda)
        {
            if (rept != null)
            {
                var dict = new Dictionary<string, string>();
                foreach (var item in lambda.Parameters)
                {
                    foreach (var (key, value) in rept)
                    {
                        if (item.Type.Equals(value) && !dict.Values.Contains(key))
                        {
                            dict.Add(item.Name, key);
                            break;
                        }
                    }
                }
                return dict;
            }
            if (BaseTabs == null)
            {
                return lambda.Parameters.ToDictionary(a => a.Name, a => "");
            }
            return BaseTabs.Concat(lambda.Parameters.ToDictionary(a => a.Name, a => "")).ToDictionary(a => a.Key, a => a.Value);
        }


        /// <summary>
        /// 解析Select
        /// </summary>
        /// <returns></returns>
        protected string ResolveSelect(MemberInfo member, Expression expression, Dictionary<string, string> parameters)
        {
            return ResolveSelect(CostName(member.Name), expression, parameters);
        }

        protected string ResolveSelect(string name, Expression expression, Dictionary<string, string> parameters)
        {
            string select;
            if (expression.NodeType == ExpressionType.Call)
            {
                select = $"{ResolveSelectFunc(expression as MethodCallExpression, parameters)}";
            }
            else
            {
                select = $"{ResolveAny(expression, parameters)}";
            }
            if (!string.IsNullOrEmpty(name))
            {
                return $"{select} AS {name}";
            }
            return select;
        }
        protected string ResolveGroup(MemberInfo member, Expression expression, Dictionary<string, string> parameters)
        {
            string name = CostName(member.Name);
            if (expression.NodeType == ExpressionType.MemberAccess)
            {
                string arg = ResolveMember(expression as MemberExpression, parameters);
                if (name == arg)
                {
                    return arg;
                }
                else
                {
                    return $"{arg} AS {name}";
                }
            }
            throw new Exception("无效分组对象");
        }
        protected string ResolveSelectFunc(MethodCallExpression call, Dictionary<string, string> pairs)
        {
            switch (call.Method.Name)
            {
                case "LongCount":
                case "Count":
                    return "COUNT(1)";
                case "Max":
                case "Min":
                case "Sum":
                case "Average":
                    LambdaExpression lambda;
                    if (call.Arguments.Count == 1)
                    {
                        lambda = GetInnerSelect(call.Arguments[0] as MethodCallExpression);
                    }
                    else
                    {
                        lambda = call.Arguments[1] as LambdaExpression;
                    }
                    string FName = call.Method.Name.ToUpper();
                    if (call.Method.Name == "Average") FName = "AVG";
                    return string.Format("{0}({1})", FName, ResolveAny(lambda.Body, GetDefaultParameters(lambda)));
                default:
                    return ResolveAny(call, pairs);
                    //throw Error.SysError("无效方法：" + call.Method.Name);
            }
        }
        protected string WhereAny(LambdaExpression lambda)
        {
            return ResolveAny(lambda.Body, GetDefaultParameters(lambda));
        }

        protected T TryCreateTable<T>(Func<T> func)
        {
            try
            {
                return func();
            }
            catch (Exception e)
            {
                if (AutoCreate && e.Message.IsMatch("^Table .* doesn't exist$"))
                {
                    new MysqlResolveTabel(TableType, sqlExecute).CopyToNewTable(GetTabName(), false);
                    return func();
                }
                throw;
            }
        }


        protected string WhereAny(UnaryExpression expression)
        {
            var lambda = (expression.Operand as LambdaExpression);
            return string.Concat("(", ResolveAny(lambda.Body, GetDefaultParameters(lambda)), ")");
        }

        protected string ResolveCustomWhere(UnaryExpression unaryExpression)
        {
            var lambdaExpression = (unaryExpression.Operand as LambdaExpression);
            var param = GetDefaultParameters(lambdaExpression);
            var body = lambdaExpression.Body;

            switch (body.NodeType)
            {
                case ExpressionType.Call:
                    var call = body as MethodCallExpression;
                    var arg = new List<ConstantExpression>() { Expression.Constant(GetValue(call.Arguments[0])) };
                    for (int i = 1; i < call.Arguments.Count; i++)
                    {
                        if (!IsOutParams(call.Arguments[i]))
                        {
                            arg.Add(Expression.Constant(ResolveAny(call.Arguments[i], param), call.Arguments[i].Type));
                        }
                        else
                        {
                            arg.Add(Expression.Constant(AppendArg("key", GetValue(call.Arguments[i])), call.Arguments[i].Type));
                        }
                    }

                    var func = Expression.Lambda(Expression.Call(call.Object, call.Method, arg));
                    return func.Compile().DynamicInvoke().ToString();
                default:
                    throw new ArgumentException("不支持的骚操作：" + body.NodeType.ToString());
            }

        }
        protected string ResolveAny(Expression expression, Dictionary<string, string> parameters, string format = null)
        {
            if (expression is UnaryExpression)
            {
                return ResolveUnary(expression as UnaryExpression, parameters, format);
            }
            if (expression is BinaryExpression)
            {
                return ResolveBinary(expression as BinaryExpression, parameters);
            }
            if (expression is ConditionalExpression)
            {
                return ResolveConditional(expression as ConditionalExpression, parameters);
            }
            if (expression is MethodCallExpression)
            {
                return ResolveFunction(expression as MethodCallExpression, parameters);
            }
            if (IsOutParams(expression, out object value))
            {
                return AppendArg("arg", value, format);
            }
            if (expression.NodeType == ExpressionType.MemberAccess)
            {
                return ResolveMember(expression as MemberExpression, parameters, format);
            }
            throw new Exception("无法解析" + expression.NodeType);
        }

        /// <summary>
        /// 字段解析
        /// </summary>
        /// <param name="memberExpression"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string ResolveMember(MemberExpression memberExpression, Dictionary<string, string> parameters, string format = null)
        {
            if (memberExpression.Expression == null)
            {
                return AppendArg("arg", GetValue(memberExpression));
            }
            else if (memberExpression.Expression.NodeType == ExpressionType.Constant)
            {
                return AppendArg(memberExpression.Member.Name, (memberExpression.Expression as ConstantExpression).Value, format);
            }
            else if (memberExpression.Expression.NodeType == ExpressionType.Parameter)
            {
                var parameter = memberExpression.Expression as ParameterExpression;
                if (parameters.ContainsKey(parameter.Name) && parameters[parameter.Name] != "")
                {
                    return parameters[parameter.Name] + "." + CostName(memberExpression.Member.Name);
                }
            }
            if ("Nullable`1".Equals(memberExpression.Member.DeclaringType?.Name) && memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
            {
                return ResolveMember((MemberExpression)memberExpression.Expression, parameters, format);
            }
            if (memberExpression.Expression.Type.Equals(typeof(DateTime)))
            {
                string funName = "";
                switch (memberExpression.Member.Name)
                {
                    case "Year":
                        funName = "YEAR";
                        break;
                    case "Month":
                        funName = "MONTH";
                        break;
                    case "DayOfWeek":
                        funName = "WEEK";
                        break;
                    case "Day":
                        funName = "DAY";
                        break;
                    case "Hour":
                        funName = "HOUR";
                        break;
                    case "Minute":
                        funName = "MINUTE";
                        break;
                    case "Second":
                        funName = "SECOND";
                        break;
                    default:
                        funName = "MICROSECOND";
                        break;
                }

                return string.Concat("EXTRACT(", funName, " from ", ResolveAny(memberExpression.Expression, parameters, format), ")");
            }
            if (format == null)
            {
                return CostName(memberExpression.Member.Name);
            }
            else
            {
                return string.Format(format, CostName(memberExpression.Member.Name));
            }
            //parameters.FirstOrDefault(a => a.Type.IsEquivalentTo())

            // memberExpression.Member.Name;

        }


        /// <summary>
        /// 一元解析
        /// </summary>
        /// <param name="binary"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string ResolveUnary(UnaryExpression unary, Dictionary<string, string> parameters, string format = null)
        {
            if (IsOutParams(unary, out object value))
            {
                return AppendArg("arg", value, format);
            }
            if (unary.NodeType == ExpressionType.Not)
            {
                return "( NOT " + ResolveAny(unary.Operand, parameters) + " )";
            }
            if (unary.NodeType == ExpressionType.Negate)
            {
                return "( - " + ResolveAny(unary.Operand, parameters) + " )";
            }
            //if (unary.NodeType == ExpressionType.Convert)
            //{
            //    return ResolveConvert(unary.Operand, unary.Type, parameters);
            //}
            return ResolveAny(unary.Operand, parameters);
        }

        /// <summary>
        /// 二元运算解析
        /// </summary>
        /// <param name="binary"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string ResolveBinary(BinaryExpression binary, Dictionary<string, string> parameters)
        {
            if (binary.NodeType == ExpressionType.Coalesce)
            { //??语法实现//Conditional
                return string.Format(" IFNULL({0},{1}) ", ResolveAny(binary.Left, parameters), ResolveAny(binary.Right, parameters));
            }
            if (binary.Left.NodeType == ExpressionType.Constant)
            {
                if ((binary.Left as ConstantExpression).Value == null)
                {
                    return string.Concat(ResolveAny(binary.Right, parameters), binary.NodeType == ExpressionType.Equal ? "IS" : "IS NOT", " NULL");
                }
            }
            if (binary.Right.NodeType == ExpressionType.Constant)
            {
                if ((binary.Right as ConstantExpression).Value == null)
                {
                    return string.Concat(ResolveAny(binary.Left, parameters), binary.NodeType == ExpressionType.Equal ? "IS" : "IS NOT", " NULL");
                }
            }
            if (binary.Right is BinaryExpression || binary.Left is BinaryExpression)
            {
                return string.Concat("(", ResolveAny(binary.Left, parameters), ResolveOperator(binary.NodeType), ResolveAny(binary.Right, parameters), ")");
            }
            else
            {
                return string.Concat(ResolveAny(binary.Left, parameters), ResolveOperator(binary.NodeType), ResolveAny(binary.Right, parameters));
            }
        }
        /// <summary>
        /// 三目运算
        /// </summary>
        /// <param name="conditional"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string ResolveConditional(ConditionalExpression conditional, Dictionary<string, string> parameters)
        {
            return $"(CASE WHEN {ResolveAny(conditional.Test, parameters)} THEN {ResolveAny(conditional.IfTrue, parameters)} ELSE {ResolveAny(conditional.IfFalse, parameters)} END)";
        }


        /// <summary>
        /// 转换解析
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="convertType"></param>
        /// <returns></returns>
        private string ResolveConvert(Expression expression, Type convertType, Dictionary<string, string> parameters)
        {
            if (IsOutParams(expression, out object value))
            {
                return AppendArg("arg", Convert.ChangeType(value, convertType));
            }
            switch (convertType.Name)
            {
                case "Int16":
                case "Int32":
                case "Int64":
                    return string.Concat(" CAST(", ResolveAny(expression, parameters), " AS SIGNED) ");
                case "UInt16":
                case "UInt32":
                case "UInt64":
                case "Boolean":
                    return string.Concat(" CAST(", ResolveAny(expression, parameters), " AS UNSIGNED) ");
                case "Decimal":
                    return string.Concat(" CAST(", ResolveAny(expression, parameters), " AS DECIMAL(18,3)) ");
                case "Single":
                    return string.Concat(" CAST(", ResolveAny(expression, parameters), " AS DECIMAL(32,20)) ");
                case "Double":
                    return string.Concat(" CAST(", ResolveAny(expression, parameters), " AS DECIMAL(64,20)) ");
                default:
                    throw Error.SystemError("不支持转换:" + convertType.Name);
            }
        }


        /// <summary>
        /// 解析字符拼接
        /// </summary>
        /// <returns></returns>
        private string ResolveStringConcat(Dictionary<string, string> parameters, params object[] strFormat)
        {
            if (strFormat.All(a => !(a is Expression) || IsOutParams(a as Expression)))
            {
                return AppendArg("ArgString", string.Join("", strFormat.Select(a => typeof(Expression).IsInstanceOfType(a) ? GetValue(a as Expression) : a)));
            }
            return string.Concat("CONCAT(", string.Join(",", strFormat.Select(a => typeof(Expression).IsInstanceOfType(a) ? ResolveAny(a as Expression, parameters) : AppendArg("ArgString", a))), ")");
        }

        /// <summary>
        /// str拼接
        /// </summary>
        /// <param name="args"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string ResolveStringFormat(IList<Expression> args, Dictionary<string, string> parameters)
        {
            var formatStr = GetValue(args[0]).ToString();
            var matchs = Regex.Matches(formatStr, "{[0-9]+}");

            List<object> append = new List<object>();
            var index = 0;
            foreach (Match match in matchs)
            {
                var left = formatStr.Substring(index, match.Index - index);
                if (left.Length > 0) append.Add(left);
                var pindex = int.Parse(match.Value.Trim(new char[] { '{', '}' })) + 1;
                append.Add(args[pindex]);
                index = match.Index + match.Value.Length;
            }
            var right = formatStr.Substring(index);
            if (right.Length > 0) append.Add(right);
            return ResolveStringConcat(parameters, append.ToArray());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="callExpression"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string ResolveFunction(MethodCallExpression call, Dictionary<string, string> parameters)
        {
            if (IsOutParams(call, out object value))
            {
                return AppendArg("arg", value);
            }
            string str = sqlExecute.CustomMethod(call.Method.Name, call.Object, call.Arguments, (ex) => ResolveAny(ex, parameters));
            if (!string.IsNullOrEmpty(str))
            {
                return str;
            }
            switch (call.Method.Name)
            {
                case "Parse":
                    return ResolveConvert(call.Arguments[0], call.Type, parameters);
                case "ToString":
                    return ResolveConvert(call.Arguments[0], typeof(string), parameters);
                case "ToInt32":
                case "ToInt64":
                case "ToDecimal":
                case "ToDouble":
                case "ToFloat":
                case "ToBool":
                    return ResolveConvert(call.Arguments[0], call.Type, parameters);
                case "Between":
                    return string.Format("{0} BETWEEN {1} AND {2}", ResolveAny(call.Arguments[0], parameters), ResolveAny(call.Arguments[1], parameters), ResolveAny(call.Arguments[2], parameters));
                case "Any":
                    return Any(call, parameters);
                case "Contains":
                    if (call.Object != null)
                    {
                        return Contains(call.Object, call.Arguments[0], parameters);
                    }
                    else
                    {
                        return Contains(call.Arguments[0], call.Arguments[1], parameters);
                    }
                case "StartsWith":
                    return string.Format(" ({0} LIKE {1}) ", ResolveAny(call.Object, parameters), ResolveStringConcat(parameters, call.Arguments[0], "%"));
                case "EndsWith":
                    return string.Format(" ({0} LIKE {1}) ", ResolveAny(call.Object, parameters), ResolveStringConcat(parameters, "%", call.Arguments[0]));
                case "IsNullOrWhiteSpace":
                    return string.Format("LENGTH(TRIM(IFNULL({0},'')))<1", ResolveAny(call.Arguments[0], parameters));
                case "IsNullOrEmpty":
                    return string.Format("LENGTH(IFNULL({0},''))<1", ResolveAny(call.Arguments[0], parameters));
                case "Count":
                case "LongCount":
                    return string.Format(" LENGTH({0}) ", ResolveAny(call.Arguments[0], parameters));
                case "IndexOf"://Mysql 索引从1开始 修正
                    return string.Format(" ( LOCATE({0},{1}) - 1 ) ", ResolveAny(call.Arguments[0], parameters), ResolveAny(call.Object, parameters));
                case "Concat":
                    return " CONCAT(" + string.Join(",", call.Arguments.Select(a => ResolveAny(a, parameters))) + ") ";
                case "Substring"://Mysql 索引 修正
                    if (call.Arguments.Count == 2)
                        return string.Format(" SUBSTRING({0},{1} + 1,{2}) ", ResolveAny(call.Object, parameters), ResolveAny(call.Arguments[0], parameters), ResolveAny(call.Arguments[1], parameters));
                    return string.Format(" SUBSTRING({0},{1} + 1) ", ResolveAny(call.Object, parameters), ResolveAny(call.Arguments[0], parameters));
                case "Replace":
                    return string.Format(" REPLACE({0},{1},{2}) ", ResolveAny(call.Object, parameters), ResolveAny(call.Arguments[0], parameters), ResolveAny(call.Arguments[1], parameters));
                case "Format":
                    return ResolveStringFormat(call.Arguments, parameters);
                case "FindInSet"://Mysql 索引 修正
                    return string.Format(" (FIND_IN_SET({0},{1}) - 1)", ResolveAny(call.Arguments[1], parameters), ResolveAny(call.Arguments[0], parameters));

                case "Max":
                case "Min":
                case "Sum":
                case "Average":
                    LambdaExpression lambda;
                    if (call.Arguments.Count == 1)
                    {
                        lambda = GetInnerSelect(call.Arguments[0] as MethodCallExpression);
                    }
                    else
                    {
                        lambda = call.Arguments[1] as LambdaExpression;
                    }
                    string FName = call.Method.Name.ToUpper();
                    if (call.Method.Name == "Average") FName = "AVG";
                    return string.Format("{0}({1})", FName, ResolveAny(lambda.Body, parameters));
                default:
                    throw new Exception(string.Format("不支持{0}方法", call.Method.Name));
            }
        }

        private LambdaExpression GetInnerSelect(MethodCallExpression methodCallExpression)
        {
            if (methodCallExpression.Method.Name != "Select")
                throw new Exception("无效方法：" + methodCallExpression.Method.Name);
            return methodCallExpression.Arguments[1] as LambdaExpression;
        }

        private Expression GetMemberExpressionP(Expression expression)
        {
            if (expression is MemberExpression)
            {
                return (expression as MemberExpression).Expression;
            }
            if (expression is UnaryExpression)
            {
                return GetMemberExpressionP((expression as UnaryExpression).Operand);
            }
            throw Error.SystemError("未知类型");
        }
        /// <summary>
        /// 子查询
        /// </summary>
        /// <param name="call"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string Any(MethodCallExpression call, Dictionary<string, string> parameters)
        {

            if (IsOutParams(call.Arguments[0], out object value) && !(value is IQueryable))
            {
                var list = value as System.Collections.IEnumerable;
                var la = (call.Arguments[1] as LambdaExpression);
                BinaryExpression binary = la.Body as BinaryExpression;
                Delegate @delegate = null;
                bool isLeft = false;

                if (la.Parameters.Any(b => b == GetMemberExpressionP(binary.Left)))
                {
                    isLeft = true;
                    @delegate = Expression.Lambda(binary.Left, la.Parameters).Compile();
                }
                if (la.Parameters.Any(b => b == GetMemberExpressionP(binary.Right)))
                {
                    @delegate = Expression.Lambda(binary.Right, la.Parameters).Compile();
                }
                List<string> setInPara = new List<string>();
                foreach (var item in list)
                {
                    setInPara.Add(AppendArg("InParameter", @delegate.DynamicInvoke(item)));
                }
                if (setInPara.Count == 0)
                {
                    setInPara.Add("0");
                }
                return string.Format("{0} IN ({1})", ResolveAny(isLeft ? binary.Right : binary.Left, parameters), string.Join(",", setInPara.ToArray()));
            }
            //子查询
            CreateAbridge();
            var keys = parameters.Keys.ToArray();
            foreach (var key in keys)
            {
                if (string.IsNullOrEmpty(parameters[key]))
                {
                    parameters[key] = Abridge;
                }
            }
            return $"EXISTS ({CreateResolve(call, this, parameters, sqlExecute: sqlExecute).BuildSql()})";
        }


        protected bool IsOutParams(Expression expression)
        {
            return IsOutParams(expression, out _);
        }

        /// <summary>
        /// 是否外部参数 返回值
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        protected bool IsOutParams(Expression expression, out object value)
        {
            try
            {
                value = Expression.Lambda(expression).Compile().DynamicInvoke();
                return true;
            }
            catch
            {
                value = null;
                return false;
            }
        }
        private string Contains(Expression expression, Expression expression2, Dictionary<string, string> parameters)
        {
            if (!typeof(System.Collections.IEnumerable).IsAssignableFrom(expression.Type))
            {
                throw new FormatException(expression.ToString() + "类型无效");
            }
            if (expression.Type.IsEquivalentTo(typeof(string)) || typeof(JToken).IsAssignableFrom(expression.Type))
            {
                return string.Format("{0} LIKE {1}", ResolveAny(expression, parameters), ResolveStringConcat(parameters, "%", expression2, "%"));
            }
            if (IsOutParams(expression, out object value))
            {
                if (value is IQueryable)
                {//in子查询

                    return string.Format("{0} IN {1}", ResolveAny(expression2, parameters), CreateResolve((value as IQueryable).Expression).BuildSql());
                }
                var list = value as System.Collections.IEnumerable;
                List<string> setInPara = new List<string>();

                foreach (var item in list)
                {
                    setInPara.Add(AppendArg("InParameter", item));
                }
                if (setInPara.Count == 0)
                {
                    setInPara.Add("0");
                }

                return string.Format("{0} IN ({1})", ResolveAny(expression2, parameters), string.Join(",", setInPara.ToArray()));
            }
            throw new FormatException(expression.ToString() + "类型无效");
        }

        private string _tabName;

        public virtual string GetTabName()
        {
            if (_tabName == null)
            {
                return _tabName = CostName(TableType.Name + (Suffix == null ? "" : ("#" + Suffix)));
            }
            return _tabName;
        }

        private void Simple(ref Type type)
        {
            if (type.IsValueType)
            {
                type = Nullable.GetUnderlyingType(type) ?? type;
            }
        }

        private ColumnAttribute GetColumn(ColumnAttribute column, Func<object, object> func, Action<object, object> setAction, string name, Type type)
        {
            if (column == null)
                return null;
            if (string.IsNullOrEmpty(column.Name))
            {
                column.Name = CostName(name);
            }
            Simple(ref type);
            column.Cost(func, setAction, name, type);
            return column;
        }

        public IEnumerable<ColumnAttribute> GetColumns(Type type)
        {
            foreach (var item in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {

                var colum = GetColumn(item.GetCustomAttribute<ColumnAttribute>(true), item.GetValue, item.SetValue, item.Name, item.PropertyType);
                if (colum != null)
                    yield return colum;
            }
            yield break;
        }

        protected object GetValue(Expression expression)
        {
            if (expression.NodeType == ExpressionType.Constant)
            {
                return (expression as ConstantExpression).Value;
            }
            return Expression.Lambda(expression).Compile().DynamicInvoke(); ;
        }
        private string ResolveOperator(ExpressionType expressionType)
        {
            switch (expressionType)
            {
                //拼接运算
                case ExpressionType.AndAlso:
                    return " AND ";
                case ExpressionType.OrElse:
                    return " OR ";
                //比较运算
                case ExpressionType.Equal:
                    return " = ";
                case ExpressionType.NotEqual:
                    return " <> ";
                case ExpressionType.LessThan:
                    return " < ";
                case ExpressionType.LessThanOrEqual:
                    return " <= ";
                case ExpressionType.GreaterThan:
                    return " > ";
                case ExpressionType.GreaterThanOrEqual:
                    return " >= ";
                //符号运算
                case ExpressionType.Add:
                    return " + ";
                case ExpressionType.Subtract:
                    return " - ";
                case ExpressionType.Multiply:
                    return " * ";
                case ExpressionType.Divide:
                    return " / ";
                //位运算
                case ExpressionType.ExclusiveOr:
                    return " ^ ";
                case ExpressionType.Or:
                    return " | ";
                case ExpressionType.And:
                    return " & ";
                case ExpressionType.Not:
                    return " ~ ";
                case ExpressionType.Modulo:
                    return " % ";
                default:
                    return "";
                    //throw new Exception(string.Format("不支持{0}此种运算符查找！", expressiontype));
            }
        }
        /// <summary>
        /// 二元条件
        /// </summary>
        /// <returns></returns>
        protected virtual string WhereBinary(string symbol, string left, string right)
        {
            return null;
        }

        /// <summary>
        /// 一元条件
        /// </summary>
        /// <returns></returns>
        protected virtual string WhereUnary(bool isTrue, string arg)
        {
            if (isTrue)
            {
                return arg;
            }
            return $"NOT {arg}";
        }

        /// <summary>
        /// 方法
        /// </summary>
        /// <returns></returns>
        protected virtual string WhereFunction(string funcName, params string[] args)
        {
            switch (funcName)
            {
                case "IsNullOrEmpty":
                    return "";
                default:
                    break;
            }
            return null;
        }

        public abstract object GetResult();

    }

}
